﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace OOLib
{
   /// <summary>
   /// Provides a collection of implementations of services. 
   /// </summary>
   /// <remarks>
   /// The factories for instantiating objects of implemetations are accessed via a service name.
   /// The ::com::sun::star::container::XContentEnumerationAccess interface can be supported optionally. 
   /// If it is suported, it is possible to enumerate all implementations that support the service specified with 
   /// the argument of ::com::sun::star::container::XContentEnumerationAccess::createContentEnumeration. 
   /// The enumerator returns interfaces. The type of the interface is not specified. Commonly this is XSingleComponentFactory.
   /// </remarks>
   public class MultiServiceFactory : ComObjectWrapper, IMultiServiceFactory, IMultiComponentFactory, IServiceInfo
   {
      #region Constructors

      /// <summary>
      /// Constructor
      /// </summary>
      /// <remarks>
      /// After using this constructor, the ComObj must be set manually!
      /// </remarks>
      public MultiServiceFactory() :
         base()
      { 
         _MultiServiceFactoryImpl = new MultiServiceFactoryImpl(this);
         _MultiComponentFactoryImpl = new MultiComponentFactoryImpl(this);
         _ServiceInfoImpl = new ServiceInfoImpl(this);
      }

      /// <summary>
      /// Constructor
      /// </summary>
      /// <param name="comObject">COM object</param>
      public MultiServiceFactory(object comObject) :
         base(comObject)
      { 
         _MultiServiceFactoryImpl = new MultiServiceFactoryImpl(this);
         _MultiComponentFactoryImpl = new MultiComponentFactoryImpl(this);
         _ServiceInfoImpl = new ServiceInfoImpl(this);
      }

      #endregion

      #region IMultiServiceFactory
      
      private MultiServiceFactoryImpl _MultiServiceFactoryImpl;

      /// <summary>
      /// Creates an instance classified by the specified name. 
      /// </summary>
      /// <param name="serviceSpecifier">Classified name of instance </param>
      /// <returns>Return a new instance.</returns>
      public object CreateInstance(string serviceSpecifier)
      {
         return _MultiServiceFactoryImpl.CreateInstance(serviceSpecifier);
      }

      /// <summary>
      /// Creates an instance classified by the specified name and passes the arguments to that instance.
      /// </summary>
      /// <param name="serviceSpecifier">Classified name of instance</param>
      /// <param name="arguments">Arguments passed to the instance</param>
      /// <returns>Return a new instance.</returns>
      public object CreateInstanceWithArguments(string serviceSpecifier, object[] arguments)
      {
         return _MultiServiceFactoryImpl.CreateInstanceWithArguments(serviceSpecifier, arguments);
      }

      /// <summary>
      /// Provides the available names of the factory to be used to create instances.
      /// </summary>
      /// <returns>Returns a sequence of all names.</returns>
      public string[] GetAvailableServiceNames()
      {
         return _MultiServiceFactoryImpl.GetAvailableServiceNames();
      }

      #endregion

      #region IMultiComponentFactory

      private MultiComponentFactoryImpl _MultiComponentFactoryImpl;

      /// <summary>
      /// Creates an instance of a component which supports the services specified by the factory. 
      /// </summary>
      /// <param name="serviceSpecifier">Service name</param>
      /// <param name="context">Context the component instance gets its deployment values from</param>
      /// <returns>Returns the component instance.</returns>
      public ComObjectWrapper CreateInstanceWithContext(string serviceSpecifier, ComponentContext context)
      {
         return _MultiComponentFactoryImpl.CreateInstanceWithContext(serviceSpecifier, context);
      }

      /// <summary>
      /// Creates an instance of a component which supports the services specified by the factory, 
      /// and initializes the new instance with the given arguments and context. 
      /// </summary>
      /// <param name="serviceSpecifier">Service name</param>
      /// <param name="arguments">Arguments</param>
      /// <param name="context">Context the component instance gets its deployment values from</param>
      /// <returns>Returns the component instance.</returns>
      public ComObjectWrapper CreateInstanceWithArgumentsAndContext(string serviceSpecifier, object[] arguments, ComponentContext context)
      {
         return _MultiComponentFactoryImpl.CreateInstanceWithArgumentsAndContext(serviceSpecifier, arguments, context);
      }

      // GetAvailableServiceNames() is already implemented by IMultiServiceFactory

      #endregion

      #region IServiceInfo

      private ServiceInfoImpl _ServiceInfoImpl;

      /// <summary>
      /// Gets the implementation name of the service implementation.
      /// </summary>
      public string ImplementationName
      {
         get
         {
            return _ServiceInfoImpl.ImplementationName;
         }
      }

      /// <summary>
      /// Tests whether the specified service is supported, i.e. implemented by the implementation.
      /// </summary>
      /// <param name="serviceName">Name of service to be tested </param>
      /// <returns>true, if service is supported, false otherwise</returns>
      public bool SupportsService(string serviceName)
      {
         return _ServiceInfoImpl.SupportsService(serviceName);
      }

      /// <summary>
      /// Provides the supported service names of the implementation, including also indirect service names.
      /// </summary>
      /// <returns>Returns a sequence of service names that are supported.</returns>
      public string[] GetSupportedServiceNames()
      {
         return _ServiceInfoImpl.GetSupportedServiceNames();
      }

      #endregion
   }

   /// <summary>
   /// Provides a collection of implementations of services. 
   /// </summary>
   /// <remarks>
   /// The factories for instantiating objects of implemetations are accessed via a service name.
   /// The ::com::sun::star::container::XContentEnumerationAccess interface can be supported optionally. 
   /// If it is suported, it is possible to enumerate all implementations that support the service specified with 
   /// the argument of ::com::sun::star::container::XContentEnumerationAccess::createContentEnumeration. 
   /// The enumerator returns interfaces. The type of the interface is not specified. Commonly this is XSingleComponentFactory.
   /// </remarks>
   public interface IMultiServiceFactory
   {
      /// <summary>
      /// Creates an instance classified by the specified name. 
      /// </summary>
      /// <param name="serviceSpecifier">Classified name of instance </param>
      /// <returns>Return a new instance.</returns>
      object CreateInstance(string serviceSpecifier);

      /// <summary>
      /// Creates an instance classified by the specified name and passes the arguments to that instance.
      /// </summary>
      /// <param name="serviceSpecifier">Classified name of instance</param>
      /// <param name="arguments">Arguments passed to the instance</param>
      /// <returns>Return a new instance.</returns>
      object CreateInstanceWithArguments(string serviceSpecifier, object[] arguments);

      /// <summary>
      /// Provides the available names of the factory to be used to create instances.
      /// </summary>
      /// <returns>Returns a sequence of all names.</returns>
      string[] GetAvailableServiceNames();
   }

   /// <summary>
   /// Implementation of the IMultiServiceFactory interface
   /// </summary>
   internal class MultiServiceFactoryImpl : IMultiServiceFactory
   {
      /// <summary>
      /// Constructor
      /// </summary>
      /// <param name="cow">COM object which should support the interface.</param>
      public MultiServiceFactoryImpl(ComObjectWrapper cow)
      {
         Cow = cow;
      }

      /// <summary>
      /// Gets the COM object wrapper which should support the interface.
      /// </summary>
      public ComObjectWrapper Cow { get; private set; }

      /// <summary>
      /// Creates an instance classified by the specified name. 
      /// </summary>
      /// <param name="serviceSpecifier">Classified name of instance </param>
      /// <returns>Return a new instance.</returns>
      /// <remarks>!!! Not tested !!!</remarks>
      public object CreateInstance(string serviceSpecifier)
      {
         Cow.CheckDisposed();
         return Cow.InvokeMethod("createInstance", serviceSpecifier);
      }

      /// <summary>
      /// Creates an instance classified by the specified name and passes the arguments to that instance.
      /// </summary>
      /// <param name="serviceSpecifier">Classified name of instance</param>
      /// <param name="arguments">Arguments passed to the instance</param>
      /// <returns>Return a new instance.</returns>
      /// <remarks>!!! Not tested !!!</remarks>
      public object CreateInstanceWithArguments(string serviceSpecifier, object[] arguments)
      {
         Cow.CheckDisposed();
         return Cow.InvokeMethod("createInstanceWithArguments", serviceSpecifier, arguments);
      }

      /// <summary>
      /// Provides the available names of the factory to be used to create instances.
      /// </summary>
      /// <returns>Returns a sequence of all names.</returns>
      /// <remarks>!!! Not tested !!!</remarks>
      public string[] GetAvailableServiceNames()
      {
         Cow.CheckDisposed();
         return (string[])Cow.InvokeMethod("getAvailableServiceNames");
      }
   }
}
